package sf.dynamicsql.dao;

import org.mybatis.dynamic.sql.delete.DeleteModel;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.insert.GeneralInsertModel;
import org.mybatis.dynamic.sql.insert.InsertSelectModel;
import org.mybatis.dynamic.sql.insert.render.BatchInsert;
import org.mybatis.dynamic.sql.insert.render.GeneralInsertStatementProvider;
import org.mybatis.dynamic.sql.insert.render.InsertSelectStatementProvider;
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
import org.mybatis.dynamic.sql.select.SelectModel;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.update.UpdateModel;
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
import sf.common.wrapper.Page;

import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;

public interface DBDynmicSQL {
    /**
     * @param provider
     * @param records
     * @param insertFast
     * @param batchSize
     * @param pkeys
     * @param keyValues
     * @param <T>
     * @return
     */
    <T> int[] insertBatch(BatchInsert<T> provider, List<T> records, boolean insertFast,
                          int batchSize, List<String> pkeys, List<Map<String, Object>> keyValues);

    /**
     * @param insertFast
     * @param batchSize
     * @param pkeys
     * @param keyValues
     * @param provider
     * @param <T>
     * @return
     */
    <T> int[] insertBatch(boolean insertFast,
                          int batchSize, List<String> pkeys, List<Map<String, Object>> keyValues, MultiRowInsertStatementProvider<T> provider);

    /**
     * @param pkeys
     * @param keyValues
     * @param provider
     * @param <T>
     * @return
     */
    <T> int insert(List<String> pkeys, Map<String, Object> keyValues, InsertStatementProvider<T> provider);

    /**
     * @param pkeys
     * @param keyValues
     * @param provider
     * @return
     */
    int insert(List<String> pkeys, Map<String, Object> keyValues, GeneralInsertStatementProvider provider);

    /**
     * @param pkeys
     * @param keyValues
     * @param provider
     * @return
     */
    int insertSelect(List<String> pkeys, Map<String, Object> keyValues, InsertSelectStatementProvider provider);

    /**
     * @param provider
     * @return
     */
    int update(UpdateStatementProvider provider);

    /**
     * @param provider
     * @return
     */
    int delete(DeleteStatementProvider provider);

    /**
     * @param start
     * @param limit
     * @param beanClass
     * @param provider
     * @param <T>
     * @return
     */
    <T> Page<T> selectPage(long start, int limit, Class<T> beanClass, SelectStatementProvider provider);

    /**
     * @param start
     * @param limit
     * @param beanClass
     * @param countProvider
     * @param listProvider
     * @param <T>
     * @return
     */
    <T> Page<T> selectPageRaw(long start, int limit, Class<T> beanClass, SelectStatementProvider countProvider,
                              SelectStatementProvider listProvider);

    /**
     * @param provider
     * @return
     */
    Object[] selectArray(SelectStatementProvider provider);

    /**
     * @param beanClass
     * @param provider
     * @param <T>
     * @return
     */
    <T> List<T> selectList(Class<T> beanClass, SelectStatementProvider provider);

    /**
     * @param beanClass
     * @param provider
     * @param start
     * @param limit
     * @param <T>
     * @return
     */
    <T> List<T> selectList(Class<T> beanClass, SelectStatementProvider provider, long start, int limit);

    /**
     * @param beanClass
     * @param provider
     * @param <T>
     * @return
     */
    <T> T selectOne(Class<T> beanClass, SelectStatementProvider provider);

    /**
     * @param provider
     * @return
     */
    List<Map<String, Object>> select(SelectStatementProvider provider);

    /**
     * @param ormIt
     * @param returnClass
     * @param provider
     * @param <T>
     */
    <T> void selectIterator(Consumer<Iterable<T>> ormIt, Class<T> returnClass, SelectStatementProvider provider);

    /**
     * @param ormStream
     * @param returnClass
     * @param provider
     * @param <T>
     */
    <T> void selectStream(Consumer<Stream<T>> ormStream, Class<T> returnClass, SelectStatementProvider provider);

    int insert(List<String> pkeys, Map<String, Object> keyValues, GeneralInsertModel generalInsertModel);

    int insertSelect(List<String> pkeys, Map<String, Object> keyValues, InsertSelectModel insertSelectModel);

    int update(UpdateModel updateModel);

    int delete(DeleteModel deleteModel);

    <T> Page<T> selectPage(long start, int limit, Class<T> beanClass, SelectModel selectModel);

    <T> Page<T> selectPageRaw(long start, int limit, Class<T> beanClass, SelectModel countSelectModel,
                              SelectModel listSelectModel);

    Object[] selectArray(SelectModel selectModel);

    <T> List<T> selectList(Class<T> beanClass, SelectModel selectModel);

    <T> List<T> selectList(Class<T> beanClass, SelectModel selectModel, long start, int limit);

    <T> T selectOne(Class<T> beanClass, SelectModel selectModel);

    List<Map<String, Object>> select(SelectModel selectModel);

    <T> void selectIterator(Consumer<Iterable<T>> ormIt, Class<T> returnClass, SelectModel selectModel);

    <T> void selectStream(Consumer<Stream<T>> ormStream, Class<T> returnClass, SelectModel selectModel);
}
